﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary.LinearEquationSolvers
{
    /// <summary>
    /// This class represents an abstract layer for all complex nonlinear system of equation 
    /// solver classes.
    /// </summary>
    [Serializable]
    public abstract class AbstractComplexNonLinearSystemSolver
    {
        /// <summary>
        /// The needed iterations for the calculation.
        /// </summary>
        protected int neededIterations;

        /// <summary>
        /// Saves if the calculation has a precision error.
        /// </summary>
        protected bool precisionError;

        /// <summary>
        /// The system of equation to solve.
        /// </summary>
        private ComplexNonLinearEquationSystem equationSystem;

        /// <summary>
        /// Initializes a new instance of the <see cref="AbstractComplexNonLinearSystemSolver"/> class.
        /// </summary>
        /// <param name="equationSystem">The complex nonlinear system of equation to solve.</param>
        protected AbstractComplexNonLinearSystemSolver(ComplexNonLinearEquationSystem equationSystem)
        {
            this.equationSystem = equationSystem;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="AbstractComplexNonLinearSystemSolver"/> class.
        /// </summary>
        /// <param name="equationSystemFunctions">The complex nonlinear system of equation to solve.</param>
        protected AbstractComplexNonLinearSystemSolver(HardMultivariateComplexFunction[] equationSystemFunctions)
        {
            if (equationSystemFunctions == (HardMultivariateComplexFunction[]) null)
            {
                throw new ArgumentNullException("equationSystemFunctions");
            }

            this.equationSystem = new ComplexNonLinearEquationSystem(equationSystemFunctions);
        }

        /// <summary>
        /// Gets a value indicating whether the calculation has a precision error.
        /// If true the result of the calculation has a precision error otherwise, false.
        /// </summary>
        /// <value>True the result of the calculation has a precision error otherwise, false.</value>
        public bool PrecisionError
        {
            get { return this.precisionError; }
        }

        /// <summary>
        /// Gets the needed iterations for the calculation.
        /// </summary>
        /// <value>The needed iterations for the calculation.</value>
        public int NeededIterations
        {
            get { return this.neededIterations; }
        }

        /// <summary>
        /// Gets or sets the nonlinear system of equation to solve.
        /// </summary>
        /// <value>The nonlinear system of equation to solve.</value>
        public ComplexNonLinearEquationSystem EquationSystem
        {
            get { return this.equationSystem; }
            set { this.equationSystem = value; }
        }

        /// <summary>
        /// Solves the complex nonlinear system of equation. The property PrecisionError have to be 
        /// checked after the calculation to be sure that the results are correct.
        /// </summary>
        /// <param name="startValues">The start values for the calculation.</param>
        /// <param name="iterations">The maximum number of iterations.</param>
        /// <param name="precision">The precision of the result.</param>
        /// <returns>The approximated numeric results, which solves the complex nonlinear system of 
        /// equation.</returns>
        public abstract GeneralComplexVector SolveNonLinearSystem(GeneralComplexVector startValues, int iterations,
                                                                  double precision);
    }
}